﻿
using Microsoft.AspNetCore.Authentication;
using Microsoft.AspNetCore.Authentication.Cookies;
using Microsoft.AspNetCore.Mvc;
using Microsoft.AspNetCore.Mvc.Filters;
using System;
using System.Collections.Generic;
using System.IO;
using System.Security.Claims;
using System.Text;
using System.Threading.Tasks;
using System.Linq;
using NetCore.Cache;
using Newtonsoft.Json;
using Newtonsoft.Json.Converters;
using Microsoft.AspNetCore.Mvc.Authorization;
using System.Reflection;
using Newtonsoft.Json.Serialization;

namespace NetCore
{

    public class BaseController : Controller, IApplicationSession
    {

        public string UserId { get => (AppHttpContext.Current.User.Identity.IsAuthenticated) ? AppHttpContext.Current.User.Claims.Where(x => x.Type == ClaimTypes.NameIdentifier).FirstOrDefault().Value : ""; }

        public string UserName { get => (AppHttpContext.Current.User.Identity.IsAuthenticated) ? AppHttpContext.Current.User.Claims.Where(x => x.Type == ClaimTypes.Name).FirstOrDefault().Value : ""; }

    
        public string UserToken {
            get {
                string token = "";
                if (string.IsNullOrWhiteSpace(token))
                {
                    if (AppHttpContext.Current.User.Identity.IsAuthenticated)
                    {
                        token = AppHttpContext.Current.User.Claims.Where(x => x.Type == ClaimTypes.Authentication).FirstOrDefault().Value;
                    }
                    if (AppHttpContext.Current.Request != null)
                    {
                        if (string.IsNullOrWhiteSpace(token))
                        {
                            token = AppHttpContext.Current.Request.Headers[AppHttpContext.TokenKeyName];
                        }
                        if (string.IsNullOrWhiteSpace(token))
                        {
                            token = CookieHelper.GetCookies(AppHttpContext.TokenKeyName);
                        }
                     
                        if (string.IsNullOrWhiteSpace(token))
                        {
                            if (AppHttpContext.Current.Request.HasFormContentType)
                            {
                                var formData =  AppHttpContext.Current.Request.Form;
                                if (formData != null && formData.Count > 0)
                                {
                                    token = formData[AppHttpContext.TokenKeyName];
                                }
                            }
                           
                        }
                    }
                }
               
                
                return token;
            }
        }

       

        public bool IsPost
        {
            get
            {
                if (this.Request.Method.Equals("POST", StringComparison.OrdinalIgnoreCase))
                {
                    return true;
                }
                return false;
            }
        }
        public bool IsAjax
        {
            get
            {
                string sheader = Request.Headers["X-Requested-With"];
                return (sheader != null && sheader == "XMLHttpRequest") ? true : false;
               
            }
        }
        public ICacheService CacheService {
            get {
                return AppHttpContext.CacheService;
            }
        }
        /// <summary>
        /// 获取当前用户
        /// </summary>
        /// <typeparam name="T"></typeparam>
        /// <returns></returns>
        public T GetUser<T>()where T:class,new()
        {
            if (!string.IsNullOrWhiteSpace(UserId)||!string.IsNullOrWhiteSpace(UserToken))
            {
               T entity= CacheService.GetCache<T>(ApplicationEnvironments.Site.UserCacheKey  + UserToken);
                if (entity == null &&!string.IsNullOrWhiteSpace(ApplicationEnvironments.Site.UserServiceInstance))
                {
                    if (!string.IsNullOrWhiteSpace(UserId))
                    {
                        object instance = ReflectionHelper.CreateInstance(ApplicationEnvironments.Site.UserServiceInstance);
                        if (instance != null)
                        {
                            var method = instance.GetType().GetMethod("GetByInfoId", new Type[] { typeof(string), typeof(string), typeof(bool) });
                            entity = (T)method.Invoke(instance, new object[] { UserId, UserToken, true });
                        }
                    }
                    
                }
                if (entity == null)
                {
                    AppHttpContext.Current.Response.Redirect("/home/logoff");
                }
                return entity;
            }
            return default(T);
        }
    

        /// <summary>
        /// ip地址
        /// </summary>
        public string IPAddress { get => AppHttpContext.Current.Connection.RemoteIpAddress.ToString(); }
        public string FormAddress { get =>   new StringBuilder()
                .Append(AppHttpContext.Current.Request.Scheme)
                .Append("://")
                .Append(AppHttpContext.Current.Request.Host)
                .Append(AppHttpContext.Current.Request.PathBase)
                .Append(AppHttpContext.Current.Request.Path)
               //.Append(AppHttpContext.Current.Request.QueryString)
                .ToString();
    }
        public string ServerAddress { get => Directory.GetCurrentDirectory(); }

        public override Task OnActionExecutionAsync(ActionExecutingContext context, ActionExecutionDelegate next)
        {
            
            return base.OnActionExecutionAsync(context, next);
        }
        public override void OnActionExecuted(ActionExecutedContext filterContext)
        {
            base.OnActionExecuted(filterContext);
        }
        public override void OnActionExecuting(ActionExecutingContext filterContext)
        {
            var allowAnonymous = filterContext.ActionDescriptor.FilterDescriptors.FirstOrDefault(x=>x.Filter.GetType()== typeof(AllowAnonymousFilter)); 
            if (allowAnonymous==null&&IsPost)
            {
                if (filterContext.ActionArguments != null && filterContext.ActionArguments.Count > 0)
                {
                    filterContext.ModelState.Clear();
                  
                    foreach (var arg in filterContext.ActionArguments)
                    {
                        if (arg.Value is EntityBase)
                        {
                            VaildHelper.CheckVaild(arg.Value, filterContext.ModelState);//验证数据类型是否正确
                        }
                    }
                }
            }
            base.OnActionExecuting(filterContext);
        }

        /// <summary>
        /// 登录
        /// </summary>
        /// <param name="userName"></param>
        /// <param name="userNo"></param>
        /// <param name="phone"></param>
        /// <param name="email"></param>
        /// <param name="password"></param>
        /// <param name="rememberMe"></param>
        public async Task SignInAsync(List<Claim> claims,string userId,string token, bool rememberMe=false)
        {
            // CookieHelper.Add("UserNo", token, 30);
            CookieHelper.Add(AppHttpContext.TokenKeyName, token, 30);
            var Identity = new ClaimsIdentity(CookieAuthenticationDefaults.AuthenticationScheme);
            Identity.AddClaims(claims);
            var userPrincipal = new ClaimsPrincipal(Identity);
            await HttpContext.SignInAsync(CookieAuthenticationDefaults.AuthenticationScheme, userPrincipal, new AuthenticationProperties
            {
                ExpiresUtc = DateTimeOffset.Now.AddMinutes(ApplicationEnvironments.Site.SessionTimeout),
                IsPersistent = true,
                AllowRefresh = true
            });
            
            //AppHttpContext.CacheService.Add(ApplicationEnvironments.Site.UserCacheKey+ userId, user);
            //signin 
            //HttpContext.Authentication.SignInAsync("Cookie", userPrincipal, new AuthenticationProperties
            //{
            //    ExpiresUtc = DateTime.UtcNow.AddMinutes(30),
            //    IsPersistent = false,
            //    AllowRefresh = false
            //});
        }

       
        public async Task SignOutAsync()
        {
            CacheService.Remove(ApplicationEnvironments.Site.UserCacheKey + UserToken);
            CookieHelper.Delete(AppHttpContext.TokenKeyName);
            await HttpContext.SignOutAsync(CookieAuthenticationDefaults.AuthenticationScheme);
        }

        public override JsonResult Json(object data)
        {
            IsoDateTimeConverter convert = new IsoDateTimeConverter();
            convert.DateTimeFormat = "yyyy-MM-dd HH:mm:ss";
            JsonSerializerSettings settings = new JsonSerializerSettings() {
              
            };
            settings.Converters.Add(convert);
       
            return new JsonResult(data, settings);
        }

        public void SetToken(string value)
        {
            if (AppHttpContext.Current.User.Identity.IsAuthenticated)
            {
                var claim = AppHttpContext.Current.User.Claims.Where(x => x.Type == ClaimTypes.Authentication).FirstOrDefault();
                var identity = AppHttpContext.Current.User.Identity as ClaimsIdentity;
                if (identity.TryRemoveClaim(claim))
                {
                    AppHttpContext.Current.User.Claims.Append(new Claim(ClaimTypes.Authentication, value));
                }
                CookieHelper.Add(AppHttpContext.TokenKeyName, value);

            }
            
        }

    }
}
